home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / misc / 40 / msdos.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-07-17  |  14.1 KB  |  657 lines

  1. /* An assortment of MSDOS functions.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include "hack.h"
  6.  
  7. #ifdef MSDOS
  8. #include <dos.h>
  9.  
  10. getuid()
  11. {
  12.     return 1;
  13. }
  14.  
  15. char *
  16. getlogin()
  17. {
  18.     return ((char *) NULL);
  19. }
  20.  
  21. #define VIDEO 0x10
  22. int display_page = -1;
  23.  
  24. void
  25. fastat(x, y, ch)
  26. register xchar x,y;
  27. char ch;
  28. {
  29.     union REGS inregs;
  30.  
  31.     if(!ch) {
  32.         impossible("At gets null at %d %d.", x, y);
  33.         return;
  34.     }
  35.     if (display_page < 0) {
  36.         inregs.h.ah = 15;
  37.         int86(VIDEO, &inregs, &inregs);
  38.         display_page = inregs.h.bh;
  39.     }
  40.     if (x != curx || y != cury) {
  41.         inregs.h.ah = 2;
  42.         inregs.h.dl = x - 1;
  43.         inregs.h.dh = y + 1;
  44.         inregs.h.bh = display_page;
  45.         int86(VIDEO, &inregs, &inregs);
  46.         curx = x;
  47.         cury = y;
  48.     }
  49.     inregs.h.ah = 14;
  50.     inregs.h.al = ch;
  51.     inregs.h.bh = display_page;
  52.     inregs.x.cx = 1;
  53.     int86(VIDEO, &inregs, &inregs);
  54.     curx++;
  55. }
  56.  
  57. tgetch()
  58. {
  59.     char ch;
  60. #ifdef DGK
  61.     ch = BIOSgetch();
  62. #else
  63.     union REGS inregs, outregs;
  64.  
  65.     do {
  66.         inregs.h.ah = 0;
  67.         int86(KEYBRD, &inregs, &outregs);
  68.     } while (outregs.x.ax == 0);
  69.     ch = outregs.h.al;
  70. #endif DGK
  71.     return ((ch == '\r') ? '\n' : ch);
  72. }
  73.  
  74.  
  75. #ifdef DGK
  76. #include <sys/types.h>
  77. #include <sys/stat.h>
  78. #include <sys/utime.h>
  79. #include <ctype.h>
  80. #include <fcntl.h>
  81.  
  82. #undef creat    /* Note that creat() is used once in this file, but
  83.          * the disk free space doesn't need not be checked as
  84.          * it will have already been checked.  Thus the undef
  85.          * can occur here.
  86.          */
  87.  
  88. #define LEVELS    "level.00"
  89. #define BONES    "bones.00"
  90. #define Sprintf (void) sprintf
  91.  
  92. extern char hackdir[], levels[], SAVEF[], bones[], permbones[];
  93. extern int ramdisk;
  94.  
  95. #ifdef SHELL
  96. #include <process.h>
  97. dosh()
  98. {
  99.     char *comspec, *getenv();
  100.     extern char orgdir[];
  101.  
  102.     if (comspec = getenv("COMSPEC")) {
  103.         end_screen();
  104.         clear_screen();
  105.         puts("To return to HACK, type \"exit\" at the DOS prompt.");
  106.         fflush(stdout);
  107.         chdirx(orgdir, 0);
  108.         if (spawnl(P_WAIT, comspec, NULL)) {
  109.             printf("\nCan't execute COMSPEC \"%s\"!\n", comspec);
  110.             flags.toplin = 0;
  111.             more();
  112.         }
  113.         chdirx(hackdir, 0);
  114.         start_screen();
  115.         docrt();
  116.     }
  117.     return(0);
  118. }
  119. #endif SHELL
  120.  
  121. /* Map the keypad to equivalent character output.  If scroll lock is turned
  122.  * on, run without stopping at interesting branches (like YUHJKLBN keys), if
  123.  * it is off, run with stopping at branches (like ^Y^U^H^J^K^L^B^N keys).
  124.  */
  125. #define KEYPADHI    83
  126. #define KEYPADLOW    71
  127. #define CTRL(ch)    (ch ^ 0x40)
  128. #define KEYBRD    0x16
  129. #define iskeypad(x)    (KEYPADLOW <= (x) && (x) <= KEYPADHI)
  130. #define SHIFT        (0x1 | 0x2)
  131. #define CONTROL        0x4
  132. static struct {
  133.     char normal, shift, ctrl;
  134.     } keypad[KEYPADHI - KEYPADLOW + 1] = {
  135.             {'y', 'Y', CTRL('Y')},    /* 7 */
  136.             {'k', 'K', CTRL('K')},    /* 8 */
  137.             {'u', 'U', CTRL('U')},    /* 9 */
  138.             {'m', 'M', 'M'},    /* - */
  139.             {'h', 'H', CTRL('H')},    /* 4 */
  140.             {'.', '.', '.'},    /* 5 */
  141.             {'l', 'L', CTRL('L')},    /* 6 */
  142.             {'p', 'P', CTRL('P')},    /* + */
  143.             {'b', 'B', CTRL('B')},    /* 1 */
  144.             {'j', 'J', CTRL('J')},    /* 2 */
  145.             {'n', 'N', CTRL('N')},    /* 3 */
  146.             {'i', 'I', 'I'},    /* Ins */
  147.             {':', ',', ','}        /* Del */
  148.             };
  149. static char
  150. BIOSgetch()
  151. {
  152.     char scan, shift_state, ch;
  153.     union REGS inregs, outregs;
  154.  
  155.     do {
  156.         inregs.h.ah = 0;
  157.         int86(KEYBRD, &inregs, &outregs);
  158.     } while (outregs.x.ax == 0);
  159.     ch = outregs.h.al;
  160.     if (!flags.BIOSok)
  161.         return (ch);
  162.     scan = outregs.h.ah;
  163.     inregs.h.ah = 2;
  164.     int86(KEYBRD, &inregs, &outregs);
  165.     shift_state = outregs.h.al;
  166.  
  167.     if (iskeypad(scan))
  168.         if (shift_state & SHIFT)
  169.             ch = keypad[scan - KEYPADLOW].shift;
  170.         else if (shift_state & CONTROL)
  171.             ch = keypad[scan - KEYPADLOW].ctrl;
  172.         else
  173.             ch = keypad[scan - KEYPADLOW].normal;
  174.     return (ch);
  175. }
  176.  
  177. dotogglepickup()
  178. {
  179.     flags.pickup = !flags.pickup;
  180.     pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
  181.     return (0);
  182. }
  183.  
  184. /* from objects.h
  185. char obj_symbols[] = {
  186.     ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
  187.     BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
  188.     WAND_SYM, RING_SYM, GEM_SYM, 0 };
  189.  */
  190. extern char obj_symbols[];
  191. static char *names[] = {"Illegal objects", "Amulets", "Edibles", "Weapons",
  192.             "Tools", "Iron balls", "Chains", "Rocks", "Armor",
  193.             "Potions", "Scrolls", "Wands", "Rings", "Gems"};
  194. char *
  195. let_to_name(let)
  196. char let;
  197. {
  198.     char *pos = index(obj_symbols, let);
  199.     extern char *HI, *HE;
  200.     /* buffer size is len(HI) + len(HE) + max len(names[]) + 1 */
  201.     static char buf[4 + 4 + 15 + 1];
  202.  
  203.     if (pos == NULL)
  204.         pos = obj_symbols;
  205.     Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
  206.     return (buf);
  207. }
  208.  
  209. /* After changing the value of flags.invlet_constant, make the current
  210.  * inventory letters the fixed ones. -dgk
  211.  */
  212. void
  213. fixinv()
  214. {
  215.     struct obj *otmp;
  216.     extern int lastinvnr;
  217.     char ilet = 'a';
  218.  
  219.     for(otmp = invent; otmp; otmp = otmp->nobj) {
  220.         otmp->invlet = ilet;
  221.         if (++ilet > 'z') ilet = 'A';
  222.     }
  223.     lastinvnr = 51;
  224. }
  225.  
  226. /* construct the string  file.level 
  227.  * This assumes there is space on the end of 'file' to append
  228.  * a two digit number.  This is true for 'bones' and 'level'
  229.  * but be careful if you use it for other things -dgk
  230.  */
  231. void
  232. name_file(file, level)
  233. char *file;
  234. int level;
  235. {
  236.     char *tf;
  237.     
  238.     if (tf = rindex(file, '.'))
  239.         Sprintf(tf+1, "%d", level);
  240. }
  241.  
  242. long
  243. freediskspace(path)
  244. char *path;
  245. {
  246.     int drive = 0;
  247.     union    REGS    inregs;
  248.     union    REGS    outregs;
  249.  
  250.     inregs.h.ah = 0x36;    /* get free space -- DOS 2.0 page D-33 */
  251.     if (path[0] && path[1] == ':')
  252.         drive = (toupper(path[0]) - 'A') + 1;
  253.     inregs.h.dl = drive;
  254.     intdos(&inregs, &outregs);
  255.     if (outregs.x.ax == 0xFFFF)
  256.         return (-1);        /* bad drive number */
  257.     return ((long) outregs.x.bx * outregs.x.cx * outregs.x.ax);
  258. }
  259.  
  260. long
  261. filesize(file)
  262. char *file;
  263. {
  264.     struct stat buf;
  265.  
  266.     if (stat(file, &buf) == 0)
  267.         return (buf.st_size);
  268.     else
  269.         return (-1L);
  270. }
  271.  
  272. long
  273. all_files_size(path)
  274. char *path;
  275. {
  276.     register int level;
  277.     long size, tmp;
  278.     char buf[PATHLEN];
  279.  
  280.     strcpy(buf, path);
  281.     for (level = 1, size = 0; level <= MAXLEVEL; level++) {
  282.         name_file(buf, level);
  283.         tmp = filesize(buf);
  284.         if (tmp > 0)
  285.             size += tmp;
  286.     }
  287.     return (size);
  288. }
  289.  
  290. void
  291. copybones(mode)
  292. int mode;
  293. {
  294.     register int fd, level;
  295.     char from[PATHLEN], to[PATHLEN];
  296.     long sizes[MAXLEVEL + 1];
  297.     extern boolean level_exists[];
  298.  
  299.     if (!ramdisk)
  300.         return;
  301.     strcpy(to, (mode == TOPERM) ? permbones : bones);
  302.     strcpy(from, (mode == TOPERM) ? bones : permbones);
  303.  
  304.     for (level = 1; level <= MAXLEVEL; level++) {
  305.         name_file(from, level);
  306.         sizes[level] = filesize(from);    /* -1 if file doesn't exist */
  307.         name_file(to, level);
  308.         (void) unlink(to);    /* remove old bones files in 'to' */
  309.     }
  310.     for (level = 1; level <= MAXLEVEL; level++) {
  311.         if (sizes[level] == -1L)
  312.             continue;
  313.         name_file(from, level);
  314.         name_file(to, level);
  315.         if (sizes[level] > freediskspace(to)) {
  316.             fprintf(stderr,
  317.                 "Not enough room to copy file '%s' to '%s'.\n",
  318.                 from, to);
  319.             goto cleanup;
  320.         }
  321.         /* We use savelev and getlev to move the bones files around,
  322.          * but savelev sets level_exists[] TRUE for this level, so
  323.          * we have to set it back FALSE again.
  324.          */
  325.         if ((fd = open(from, 0)) < 0) {
  326.             fprintf(stderr, "Warning: can't open '%s'.\n", from);
  327.             continue;
  328.         } else {
  329.             sizes[level] = 0;    /* 'from' bones exists */
  330.             getlev(fd, 0, level);
  331.             (void) close(fd);
  332.             if ((fd = creat(to, FMASK)) < 0) {
  333.                 fprintf(stderr,
  334.                     "Warning: can't create '%s'.\n", to);
  335.                 continue;
  336.             } else {
  337.                 savelev(fd, level);
  338.                 (void) close(fd);
  339.                 level_exists[level] = FALSE;    /* see above */
  340.             }
  341.         }
  342.     }
  343.     /* If we are copying bones files back to permanent storage, unlink
  344.      * the bones files in the LEVELS directory.
  345.      */
  346.     if (mode == TOPERM)
  347.         for (level = 1; level <= MAXLEVEL; level++) {
  348.             if (sizes[level] == -1)
  349.                 continue;
  350.             name_file(from, level);
  351.             (void) unlink(from);
  352.         }
  353.     return;
  354.  
  355. cleanup:
  356.     /* Ran out of disk space!  Unlink the "to" files and issue an
  357.      * appropriate message.
  358.      */
  359.     for (level = 1; level <= MAXLEVEL; level++)
  360.         if (sizes[level] == 0) {
  361.             name_file(to, level);
  362.             (void) unlink(to);
  363.         }
  364.     fprintf(stderr, "There is not enough room in ");
  365.     if (mode == TOPERM) {
  366.         fprintf(stderr, "permanent storage for bones files!\n");
  367.         fprintf(stderr,
  368.             "Bones will be left in LEVELS directory '%s'!\n",
  369.             levels[0] ? levels : ".");
  370.             return;
  371.     } else {
  372.         fprintf(stderr,    "LEVELS directory '%s' to copy bones files!\n",
  373.             levels[0] ? levels : ".");
  374.         getreturn("to quit");
  375.         settty("Be seeing you ...\n");
  376.         exit(0);
  377.     }
  378. }
  379.  
  380. saveDiskPrompt(start)
  381. int start;
  382. {
  383.     extern saveprompt;
  384.     char buf[BUFSIZ];
  385.     int i, newname = FALSE;
  386.  
  387.     if (saveprompt) {
  388.         remember_topl();
  389.         home();
  390.         cl_end();
  391.         printf("If save file is on a SAVE disk, put that disk in now.\n");
  392.         cl_end();
  393.         printf("Name of save file (default: '%s'%s) ? ", SAVEF,
  394.             start ? "" : ", <Esc> aborts save");
  395.         fflush(stdout);
  396.         getlin(buf);
  397.         if (!start && buf[0] == '\033') {
  398.             home();
  399.             cl_end();
  400.             curs(1, 2);
  401.             cl_end();
  402.             return 0;
  403.         }
  404.         for (i = 0; buf[i]; i++)
  405.             if (!isspace(buf[i])) {
  406.                 strncpy(SAVEF, buf, PATHLEN);
  407.                 break;
  408.             }
  409.     }
  410.     return 1;
  411. }
  412.  
  413. /* Prompt for the game disk, then check if you can access the record file.
  414.  * If not, warn the player.
  415.  */
  416. void
  417. gameDiskPrompt()
  418. {
  419.     FILE    *fp;
  420.     extern saveprompt;
  421.  
  422.     if (saveprompt) {
  423.         fputc('\n', stderr);
  424.         getreturn("when the GAME disk is ready");
  425.     }
  426.     if ((fp = fopen(RECORD, "r")))    /* check for GAME disk */
  427.         fclose(fp);
  428.     else {
  429.         fprintf(stderr,
  430.             "\n\nWARNING: I can't find record file '%s'!\n",
  431.              RECORD);
  432.         fprintf(stderr,
  433.             "If the GAME disk is not in, put it in now.\n");
  434.         getreturn("to continue");
  435.     }
  436. }
  437.  
  438. #define CONFIGFILE    "hack103.cnf"
  439. void
  440. read_config_file()
  441. {
  442.     char    config[FILENAME], tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
  443.     char    buf[BUFSZ], *bufp;
  444.     FILE    *fp;
  445.     extern    char plname[];
  446.     extern    int saveprompt;
  447.  
  448.     tmp_ramdisk[0] = 0;
  449.     tmp_levels[0] = 0;
  450.     strcpy(config, hackdir);
  451.     append_slash(config);
  452.     strcat(config, CONFIGFILE);
  453.     if (!(fp = fopen(config, "r"))) {
  454.         fprintf(stderr, "Warning: no configuration file '%s'!\n",
  455.             config);
  456.         getreturn("to continue");
  457.         return;
  458.     }
  459.     while (fgets(buf, BUFSZ, fp)) {
  460.         if (*buf == '#')        /* comment first character */
  461.             continue;
  462.  
  463.         /* remove any trailing whitespace
  464.          */
  465.         bufp = index(buf, '\n');
  466.         while (bufp > buf && isspace(*bufp))
  467.             bufp--;
  468.         if (bufp == buf)
  469.             continue;        /* skip all-blank lines */
  470.         else
  471.             *(bufp + 1) = 0;    /* 0 terminate line */
  472.  
  473.         /* find the '=' separating option name from option value
  474.          */
  475.         if (!(bufp = strchr(buf, '='))) {
  476.             fprintf(stderr, "Bad option line: '%s'\n", buf);
  477.             getreturn("to continue");
  478.             continue;
  479.         }
  480.         
  481.         /* move past whitespace between '=' and option value
  482.          */
  483.         while (isspace(*++bufp))
  484.             ;
  485.  
  486.         /* Now go through the possible configurations
  487.          */
  488.         if (!strncmp(buf, "RAMDISK", 3)) {
  489.             strncpy(tmp_ramdisk, bufp, PATHLEN);
  490.  
  491.         } else if (!strncmp(buf, "LEVELS", 4)) {
  492.             strncpy(tmp_levels, bufp, PATHLEN);
  493.  
  494.         } else if (!strncmp(buf, "OPTIONS", 4)) {
  495.             parseoptions(bufp, TRUE);
  496.             if (plname[0])        /* If a name was given */
  497.                 plnamesuffix();    /* set the character class */
  498.  
  499.         } else if (!strncmp(buf, "SAVE", 4)) {
  500.             char *ptr;
  501.             if (ptr = index(bufp, ';')) {
  502.                 *ptr = '\0';
  503.                 if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
  504.                     saveprompt = FALSE;
  505.             }
  506.             (void) strncpy(SAVEF, bufp, PATHLEN);
  507.             append_slash(SAVEF);
  508.  
  509.         } else if (!strncmp(buf, "GRAPHICS", 4)) {
  510.             struct symbols s;
  511.  
  512.             if (sscanf(bufp, "%u%u%u%u%u%u%u%u%u", &s.vwall,
  513.                     &s.hwall, &s.tlcorn, &s.trcorn, &s.blcorn,
  514.                     &s.brcorn, &s.door, &s.room, &s.corr) == 9)
  515.                 symbol = s;
  516.             else {
  517.                 fprintf(stderr,
  518.                     "GRAPHICS did not contain 9 values\n");
  519.                 getreturn("to continue");
  520.             }
  521.  
  522.         } else if (!strncmp(buf, "DISPLAY", 4)) {
  523.             /* There was a variable called DISPLAY which never
  524.              * work very well and was too confusing.  Leave this
  525.              * code in here for now for 'backward compatibility'.
  526.              */
  527.             ;
  528.  
  529.         } else {
  530.             fprintf(stderr, "Bad option line: '%s'\n", buf);
  531.             getreturn("to continue");
  532.         }
  533.     }
  534.     fclose(fp);
  535.  
  536.     strcpy(permbones, tmp_levels);
  537.     if (tmp_ramdisk[0]) {
  538.         strcpy(levels, tmp_ramdisk);
  539.         if (strcmpi(permbones, levels))        /* if not identical */
  540.             ramdisk = TRUE;
  541.     } else
  542.         strcpy(levels, tmp_levels);
  543.     strcpy(bones, levels);
  544. }
  545.  
  546. void
  547. set_lock_and_bones()
  548. {
  549.     if (!ramdisk) {
  550.         strcpy(levels, permbones);
  551.         strcpy(bones, permbones);
  552.     }
  553.     append_slash(bones);
  554.     strcat(bones, BONES);
  555.     append_slash(permbones);
  556.     strcat(permbones, BONES);
  557.     strcpy(lock, levels);
  558.     append_slash(lock);
  559.     strcat(lock, LEVELS);
  560. }
  561.  
  562. void
  563. append_slash(name)
  564. char *name;
  565. {
  566.     char *ptr;
  567.  
  568.     if (!name[0])
  569.         return;
  570.     ptr = name + (strlen(name) - 1);
  571.     if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
  572.         *(ptr + 1) = '\\';
  573.         *(ptr + 2) = 0;
  574.     }
  575. }
  576.  
  577.  
  578. check_then_creat(file, pmode)
  579. char *file;
  580. int pmode;
  581. {
  582.     long freespace = freediskspace(file);
  583.     extern boolean restoring;
  584.  
  585.     if (freespace < 0)
  586.         return (-1);
  587.     if (!restoring && freespace < 8000L) {
  588.         pline("â—†HACK is almost out of disk space for making levels!");
  589.         pline("You should save the game now.  Save this game [y/n] ?");
  590.         fflush(stdout);
  591.         if (getchar() == 'y')
  592.             dosave();
  593.         return(-1);    /* In case he decides not to save don't let him
  594.                  * change levels
  595.                  */
  596.     }
  597.     return( creat(file, pmode));
  598. }
  599.  
  600. void
  601. getreturn(str)
  602. char *str;
  603. {
  604.     int ch;
  605.  
  606.     fprintf(stderr, "Hit <RETURN> %s.", str);
  607.     while ((ch = getchar()) != '\n')
  608.         putch(ch);
  609. }
  610.  
  611. #define SELECTDISK    0xE
  612. void
  613. chdrive(str)
  614. char *str;
  615. {
  616.     char *ptr;
  617.     union REGS inregs;
  618.     char drive;
  619.  
  620.     if ((ptr = index(str, ':')) != NULL) {
  621.         drive = toupper(*(ptr - 1));
  622.         inregs.h.ah = SELECTDISK;
  623.         inregs.h.dl = drive - 'A';
  624.         intdos(&inregs, &inregs);
  625.     }
  626. }
  627.  
  628. #endif DGK
  629.  
  630. /* Do a chdir back to the original directory
  631.  */
  632. #undef exit
  633. #if defined(MSDOS) && defined(LINT_ARGS)
  634. void
  635. #endif
  636. msexit(code)
  637. {
  638. #ifdef CHDIR
  639.     extern char orgdir[];
  640. #endif CHDIR
  641.  
  642. #ifdef DGK
  643.     fflush(stdout);
  644.     if (ramdisk)
  645.         copybones(TOPERM);
  646. #endif DGK
  647. #ifdef CHDIR
  648.     chdir(orgdir);    /* do the chdir, but not with chdirx */
  649. #    ifdef DGK
  650.         chdrive(orgdir);
  651. #    endif DGK
  652. #endif CHDIR
  653.     exit(code);
  654. }
  655.  
  656. #endif MSDOS
  657.